/*
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

#include "stdinc.h"

#include "IpGrant.h"
#include "File.h"


// #define IpGrant_TESTING


bool IpGrant::load()
{
	bool bRet = false;
	Lock l(cs);

	_ipList = boost::shared_ptr<IPList>(new IPList());

	try
	{
		string filePath = Util::getConfigPath() + "IPGrant.ini";
		string data = File(filePath, File::READ, File::OPEN).read();
		
		// Parse Data
		ParseData(data);

#if defined(IpGrant_TESTING)		

		bool test1 = check("10.1.62.12"); // 10.1.62.1/24
		bool test2 = check("192.168.0.2"); // 192.168.0.1-192.168.0.3
		bool test3 = check("62.254.12.11"); 
		bool test4 = check("192.168.13.6");  // 192.168.13.6
		bool test5 = check("12.0.0.14"); // 12.0.0.0/255.255.255.0

		bool testX = test1|test2|test3|test4|test5;
#endif
		bRet = true;
	}
	catch (const Exception& e)
	{
		dcdebug("IpGrant::load: %s\n", e.getError().c_str());
	}


	return bRet;
}


bool IpGrant::check(const string& aIP)
{
	Lock l(cs);
	if (_ipList.get())
		return _ipList.get()->CheckNumber(aIP);

	return false;
}

//#IPGrant.ini Address
//#10.1.62.1/24
//#10.0.0.0/255.255.255.0
//#192.168.0.1-192.168.0.3
//#192.168.13.6

void IpGrant::ParseData(const std::string& l_data)
{
	string::size_type linestart = 0;
	string::size_type lineend = 0;
	for (;;)
	{
		lineend = l_data.find('\n', linestart);
		if (lineend == string::npos) break;
		const string rawline = l_data.substr(linestart, lineend - linestart - 1);
		// Remove Spaces
		string line = "";
		for (size_t i = 0; i<rawline.length(); i++)
		{
			if (rawline.substr(i,1) != " ")
				line+=rawline.substr(i,1);
		}
		//
		if (!line.empty() && line.substr(0,1) != "#" )
		{
			// Parse with ip/mask or ip-ip or ip
			string::size_type mask_pos = line.find('/');
			string::size_type range_pos = line.find('-');
			if (mask_pos != string::npos)
			{
				string ip = line.substr(0, mask_pos);
				string mask = line.substr(mask_pos+1);
				if (mask.find('.') != string::npos)
				{
					_ipList.get()->Add(ip,mask);
				}else
				{
					UINT32 maskLevel = Util::toUInt32(mask);
					_ipList.get()->Add(ip, maskLevel);
				}
			}else
				if (range_pos != string::npos)
				{
					string fromIP = line.substr(0, range_pos);
					string toIP = line.substr(range_pos+1);
					_ipList.get()->AddRange(fromIP, toIP);
				}else
				{
					_ipList.get()->Add(line);
				}
		}
		linestart = lineend + 1;
	}
}